/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package io.renren.modules.app.service.impl;


import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.wxpay.sdk.WXPayConstants;
import io.renren.common.aliPay.AliConfig;
import io.renren.common.config.BaseConstant;
import io.renren.common.enums.ErrorCode;
import io.renren.common.exception.RRException;
import io.renren.common.utils.AliMessageSendComponent;
import io.renren.common.utils.BaseUtil;
import io.renren.common.utils.CheckParam;
import io.renren.common.utils.RedisUtils;
import io.renren.common.wxPay.WxPayHelper;
import io.renren.modules.app.entity.BalanceLogEntity;
import io.renren.modules.app.entity.BalanceOrderEntity;
import io.renren.modules.app.entity.CustomerEntity;
import io.renren.modules.app.service.BalanceLogService;
import io.renren.modules.app.service.BalanceOrderService;
import io.renren.modules.app.service.CustomerService;
import io.renren.modules.app.service.PublicService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;


@Service("publicService")
@Slf4j
public class PublicServiceImpl implements PublicService {


    @Resource
    private AliMessageSendComponent aliMessageSendComponent;

    @Resource
    private BaseConstant baseConstant;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    protected WxPayHelper wxPayHelper;

    @Resource
    public BalanceOrderService balanceOrderService;

    @Resource
    private CustomerService customerService;

    @Resource
    private BalanceLogService balanceLogService;

    @Resource
    protected AliConfig aliConfig;

    public static final String TRADE_SUCCESS = "TRADE_SUCCESS"; //支付成功标识
    public static final String TRADE_CLOSED = "TRADE_CLOSED";//交易关闭
    @Override
    public void sendSms(String mobile) {
        if (!CheckParam.isMobile(mobile)) {
            throw new RRException("请输入正确的手机号", ErrorCode.PARAM_ERROR.getCode());
        }
        //缓存的图形验证码
        //String cachedKaptchaCode = redisRepository.get(baseConstant.getKaptchaImageCodeCachePrefix() + "." + phoneNumber);

        //如果此处找不到图像验证码的话就直u接抛出错误
//        if(CheckParam.isNull(cachedKaptchaCode) || !kaptchaCode.equalsIgnoreCase(cachedKaptchaCode))
//        throw new BusinessException(ErrorCode.ERROR_KAPTCHA_CODE_INVALID.getCode(),ErrorCode.ERROR_KAPTCHA_CODE_INVALID.getMessage());

        //如果上次的短信验证码没有过期则不用发送短信验证码
        String theLastMessageRegCode = redisUtils.get(baseConstant.getMessageRegCachePrefix() + "." + mobile);

        if (!CheckParam.isNull(theLastMessageRegCode)) {
            redisUtils.delete(baseConstant.getMessageRegCachePrefix() + "." + mobile);
            throw new RRException(ErrorCode.ERROR_SEND_MESSAGE.getMessage(),ErrorCode.ERROR_SEND_MESSAGE.getCode());
        }

        String randomString = BaseUtil.randString(6);


        log.info(">>>>>>>>>>>>>>>执行发送注册短信 : <<<<<<<<<<<<<<<<验证码 : " + mobile + "验证码为 :  " + randomString);

        try {
            aliMessageSendComponent.sendRegMessageCode(mobile, randomString);
            /*Map<String, String> resultMap = clMessageSendComponent.ClSendMeaasge(phoneNumber, randomString);
            //发送失败
            if (!resultMap.get("code").equalsIgnoreCase("0")){
                throw new BusinessException(ErrorCode.ERROR_SEND_MESSAGE.getCode(),ErrorCode.ERROR_SEND_MESSAGE.getMessage());
            }*/
            redisUtils.set(baseConstant.getMessageRegCachePrefix() + "." + mobile, randomString);
        } catch (Exception e) {
            log.info("发送注册短信出现异常 : " + e.getMessage(), e);
            return;
        }
    }
    /**
     *微信支付回调
     * @param
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public String notifyPay(HttpServletRequest request, HttpServletResponse response) {
        String inputLine;
        String notityXml = "";
        String result = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
            final Map<String, String> resMap = wxPayHelper.checkSign(notityXml);
            log.debug("微信回调数据:{}", JSON.toJSONString(resMap));
            String orderCode = resMap.get("out_trade_no");
            String tradeNo = resMap.get("transaction_id");
            String timeEnd = resMap.get("time_end");
            String totalFee = resMap.get("total_fee");

//            Order order = orderRepository.findAllByOrderCode(orderCode);
//            Assert.notNull(order, "未查询到订单");
//            if (!order.getTotal().equals(Integer.valueOf(totalFee))) {
//                throw new TrException(666, "金额不相同");
//            }
//            super.orderPaidHandler(order);
//            order.setTradeNo(tradeNo);
//            order.setPayTime(Timestamp.valueOf(LocalDateTime.parse(timeEnd, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))));
//            orderRepository.save(order);
            this.orderDeal(orderCode);
            result = respXml(WXPayConstants.SUCCESS, "OK");
        } catch (Exception e) {
            e.printStackTrace();
            result = respXml("fail", "xml获取失败");
        }
        if (StringUtils.isEmpty(notityXml)) {
            result = respXml("fail", "xml为空");
        }
        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>微信回调返回结果:{}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", result);
        return result;
    }

    @Override
    public void aliNotify(HttpServletRequest request, HttpServletResponse response) {
        //接收参数进行校验
        Map<String, String> parameters = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
            String key = entry.getKey();
            String[] values = entry.getValue();
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            parameters.put(key, valueStr);
        }
        log.info("parameters is [parameters={}]", parameters);
        String appId = request.getParameter("app_id");//appid
        String merchantOrderNo = request.getParameter("out_trade_no");//商户订单号

//        String orderId = cashMapper.getCashByMerchantOrderNo(merchantOrderNo).getOrderId();
//        if (orderId == null) {
//            log.error("orderId is null");
//            ReturnData.fail(ReturnCode.SERVER_EXCEPTION);
//        }
//        log.info("orderId: {}", orderId);
        String payState = request.getParameter("trade_status");//交易状态
        String encodeOrderNum = null;
//        cashLogMapper.add(request.getParameter("out_trade_no"), "NOTIFY", JSON.toJSONString(parameters), new Date());
        try {
            encodeOrderNum = URLDecoder.decode(request.getParameter("passback_params"), "UTF-8");
            log.info("encodeOrderNum is [encodeOrderNum={}]", encodeOrderNum);

            boolean signVerified;
            signVerified = AlipaySignature.rsaCheckV1(parameters, aliConfig.getPublicKey(), "UTF-8", aliConfig.getSignType());//验证签名
            log.info("signVerified is [signVerified={}]", signVerified);
            if (signVerified) { //通过验证
                log.info("payState: {}", payState);
                if (payState.equals(TRADE_SUCCESS)) {
                    //判断订单号与插入的订单号是否一样
                    if (merchantOrderNo.equals(encodeOrderNum) == false || aliConfig.getAppId().equals(appId) == false) {
                        log.info("vali failure");
//                        cashMapper.update(merchantOrderNo, 4);

                        response.getOutputStream().print("failure");
                        return;
                    }
//                    cashMapper.update(merchantOrderNo, 3);
//                    orderMapper.afterPay(orderId);
                    response.getOutputStream().print("success");
                    return;
                } else if (payState.equals(TRADE_CLOSED)) { //交易关闭
//                    cashMapper.update(merchantOrderNo, 7);
                } else {
//                    cashMapper.update(merchantOrderNo, 4);
                    response.getOutputStream().print("failure");
                    return;
                }
            } else {
                //签名校验失败更状态
//                cashMapper.update(merchantOrderNo, 4);
                response.getOutputStream().print("failure");
                return;
            }
            log.info("encodeOrderNum is  [encodeOrderNum={}]", encodeOrderNum);
//            cashMapper.update(merchantOrderNo, 4);
            response.getOutputStream().print("failure");
            return;
        } catch (AlipayApiException e) {
            log.error(e.getErrMsg());
            throw new RuntimeException("调用支付宝接口发生异常");
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage());
            throw new RuntimeException("URLDecoderf发生异常");
        } catch (IOException e) {
            log.error(e.getMessage());
            throw new RuntimeException("IO发生异常");
        }
    }


    private void orderDeal(String orderNumber){
        String cutCode = orderNumber.substring(0,4);
        switch (cutCode){
            case "YEDD":
                BalanceOrderEntity balanceOrderEntity = balanceOrderService.getOne(new QueryWrapper<BalanceOrderEntity>().eq("order_number",orderNumber));
                if(!CheckParam.isNull(balanceOrderEntity)){
//                    Boolean ret =  balanceOrderService.updateById(balanceOrderEntity);
                    Boolean ret =  balanceOrderService.update(null, new UpdateWrapper<BalanceOrderEntity>().eq("id",balanceOrderEntity.getId()).eq("pay_status",0).set("pay_status",1).set("pay_type",1).set("pay_time",new Date()));
                    if(ret){
                        Boolean addRet = customerService.update(null,new UpdateWrapper<CustomerEntity>().eq("user_id",balanceOrderEntity.getUserId()).setSql(" balance = balance + " +balanceOrderEntity.getMoney()));
                        if(addRet){
                            CustomerEntity customer = customerService.getById(balanceOrderEntity.getUserId());
                            BalanceLogEntity balanceLog = new BalanceLogEntity();
                            balanceLog.setUserId(balanceOrderEntity.getUserId());
                            balanceLog.setCreateTime((int) LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")));
                            balanceLog.setSource(6);
                            balanceLog.setType(1);
                            balanceLog.setRemark("余额充值");
                            balanceLog.setNum(balanceOrderEntity.getMoney());
                            balanceLog.setNowNum(customer.getBalance());
                            balanceLog.setDetailRemark("余额充值");
                            balanceLog.setOrderNumber(balanceOrderEntity.getOrderNumber());
                            balanceLogService.save(balanceLog);
                        }
                    }
                }
                break;
            case "SPDD":
                break;
            default:
                break;
        }
    }
    /**
     * @author Lee
     * @description 微服务器响应
     * @date 2020-02-23 17:08
     **/
    public String respXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<String, String>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        return "<xml><return_code><![CDATA[" + return_code + "]]>" +
                "</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }

    @Override
    @Async
    public void dataDeal() {
        try {
            Thread.sleep(5000);
            System.out.println(11111);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
